
from rest_framework import serializers
from goods.models import SKU,SKUSpecification,GoodsCategory,SPU,SPUSpecification,SpecificationOption

# 选项表序列化器
class SpecOptModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = SpecificationOption
        fields = [
            'id',
            'value'
        ]

# 规格表序列化器
class SpecModelSerializer(serializers.ModelSerializer):
    spu = serializers.StringRelatedField()
    spu_id = serializers.IntegerField()

    # options隐藏字段，记录关联从表SpecificationOption多个对象
    options = SpecOptModelSerializer(many=True)

    class Meta:
        model = SPUSpecification
        fields = [
            'id',
            'name',
            'spu',
            'spu_id',
            'options'
        ]


# SPU序列化器
class SPUSimpleSerializer(serializers.ModelSerializer):
    class Meta:
        model = SPU
        fields = [
            'id',
            'name'
        ]

# 分类信息序列化器
class SKUCateModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = [
            'id',
            'name'
        ]

# 自定义SKUSpecification序列化器
class SKUSpecModelSerializer(serializers.ModelSerializer):
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()
    class Meta:
        model = SKUSpecification
        fields = [
            'spec_id',
            'option_id'
        ]

from django.db import transaction
# SKU序列化器
class SKUModelSerializer(serializers.ModelSerializer):
    spu = serializers.StringRelatedField()
    spu_id = serializers.IntegerField()
    category = serializers.StringRelatedField()
    category_id = serializers.IntegerField()

    # specs隐藏字段，记录关联的从表SKUSpecification多个对象
    specs = SKUSpecModelSerializer(many=True)

    class Meta:
        model = SKU
        fields = "__all__" # 主键隐藏和显示定义


    def create(self, validated_data):
        # 结论：目前序列化器create方法，无法根据specs字段，来插入中间表数据,所以重写自己实现
        # specs = [{spec_id: 4, option_id: 8}, {spec_id: 5, option_id: 11}]
        # 1、从有效数据中提取并去除specs字段
        specs = validated_data.pop('specs')

        with transaction.atomic():
            save_id = transaction.savepoint()

            try:
                # 2、新建SKU(主表)
                sku = super().create(validated_data) # 调用原序列化器的create方法新建sku
                # 3、根据specs新建中间表数据，记录和表达sku的规格和选项
                for temp in specs:
                    # temp = {spec_id: 4, option_id: 8}
                    temp['sku_id'] = sku.id # {sku_id: 17, spec_id: 4, option_id: 8}
                    SKUSpecification.objects.create(**temp)
            except Exception as e:
                # 数据插入失败 —— 一致性被破坏，回滚
                transaction.savepoint_rollback(save_id)
                raise serializers.ValidationError("新建失败！")

            transaction.savepoint_commit(save_id)

        return sku

    def update(self, instance, validated_data):
        # specs: [{spec_id: "4", option_id: 9}, {spec_id: "5", option_id: 12}]
        specs = validated_data.pop('specs')

        with transaction.atomic():
            save_id = transaction.savepoint()

            try:
                sku = super().update(instance, validated_data)
                # TODO: 更新中间表
                # (1)、删除原有中间表记录的规格和选项
                SKUSpecification.objects.filter(sku_id=sku.id).delete()
                # (2)、根据specs插入新的规格和选项
                for temp in specs:
                    # temp = {spec_id: "4", option_id: 9}
                    temp['sku_id'] = sku.id # {sku_id: 18, spec_id: "4", option_id: 9}
                    SKUSpecification.objects.create(**temp)
            except Exception as e:
                transaction.savepoint_rollback(save_id)
                raise serializers.ValidationError("更新失败！")

            transaction.savepoint_commit(save_id)

        return sku






